package org.huawei260.TiKu.ODsuanfa;

import java.util.Arrays;
import java.util.StringJoiner;

/**
 * @Author: qingle
 * @Date: 2024/10/28-16:11
 * @Description: 2535 【模拟】2024D多段线数据压缩
 *
 * 下图中，每个方块代表一个像素，每个像素用其行号和列号表示。
 *
 *
 *
 * 为简化处理，多段线的走向只能是水平、竖直、斜向45度。 上图中的多段线可以用下面的坐标串表示:(2,8),(3,7),(3,6),(3,5),(4,4),(5,3),(6,2),(7,3),(8,4),(7,5)。 但可以发现，这种表示不是最简的，其实只需要存储6个蓝色的关键点即可，它们是线段的起点、拐点、终点，而剩下4个点是冗余的。 现在，请根据输入的包含有冗余数据的多段线坐标列表，输出其最化的结果。
 *
 * 输入格式
 * 形如2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5
 *
 * 1、所有数字以空格分隔，每两个数字一组，第一个数字是行号，第二个数字是列号;
 *
 * 2、行号和列号范围为[0,64)，用例输入保证不会越界，考生不必检查;
 *
 * 3、输入数据至少包含两个坐标点。
 *
 * 输出格式
 * 形如2 8 3 7 3 5 6 2 8 4 7 5
 *
 * 压缩后的最简化坐标列表，和输入数据的格式相同。
 *
 * @version: 1.0
 */
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringJoiner;
public class D_2024D_2535__模拟多段线数据压缩 {

//	public class Main {
		public static void main(String[] args) {
			Scanner sc = new Scanner(System.in);
			int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
			System.out.println(getResult(nums));
		}

		public static String getResult(int[] nums) {
			StringJoiner sj = new StringJoiner(" ");

			// 上一个点坐标（preX, preY）
			int preX = nums[0];
			int preY = nums[1];

			// 上一次的运动方向（preDirectX, preDirectY）
			int preDirectX = 0;
			int preDirectY = 0;

			for (int i = 2; i < nums.length; i += 2) {
				// 当前点坐标（curX, curY）
				int curX = nums[i];
				int curY = nums[i + 1];

				// 上一个点到当前点的偏移量（offsetX, offsetY）
				int offsetX = curX - preX;
				int offsetY = curY - preY;

				// 根据偏移量得出本次的运动方向
				int base = Math.max(Math.abs(offsetX), Math.abs(offsetY));
				int directX = offsetX / base;
				int directY = offsetY / base;

				// 如果两次运动的方向不同
				if (directX != preDirectX || directY != preDirectY) {
					// 则上一个点是拐点，需要记录下来
					sj.add(preX + " " + preY);
				}

				preX = curX;
				preY = curY;

				preDirectX = directX;
				preDirectY = directY;
			}

			// 注意收尾
			sj.add(preX + " " + preY);

			return sj.toString();
		}
	}